﻿open System
open System.Collections.Generic
open System.Threading
open System.Windows.Forms
open System.Drawing
open Program
        
type WaitControl(timer:Timer) as c =
    inherit UserControl()
            
    let mutable theta = 0.f
    let cx,cy = 31.f, 31.f
    let myBrush = new Drawing2D.LinearGradientBrush(Point(0,0),Point(100,100), Color.DarkBlue, Color.Coral)
    let myBrush2 = new Drawing2D.LinearGradientBrush(Point(0,0),Point(100,120), Color.Blue, Color.Black)

    do  
        c.SetStyle(ControlStyles.OptimizedDoubleBuffer ||| ControlStyles.AllPaintingInWmPaint, true)
        let gp = new Drawing2D.GraphicsPath()
        gp.AddEllipse(0, 0, int cx*2, int cy*2)
        c.Region <- new Region(gp);
        timer.Tick.Add( fun _ -> 
                              theta<-(theta+0.3f) % (float32 (System.Math.PI*2.))
                              c.Invalidate() 
                         )
       
    override c.OnPaint(e) =
        base.OnPaint(e)
        //c.Visible<-true
        let g = e.Graphics
        g.SmoothingMode <- System.Drawing.Drawing2D.SmoothingMode.AntiAlias
            
        g.FillEllipse(myBrush2, cx-20.f, cy-20.f, 40.f, 40.f)
        let x = cx + 18.f * cos(theta)
        let y = cy + 18.f * sin(theta)
        g.DrawLine(Pens.White, cx,cy, x,y)
        g.FillEllipse(Brushes.White, x-5.f,y-5.f,10.f,10.f)
        g.DrawArc(new Pen(myBrush,5.f),cx-30.f,cy-30.f,60.f,60.f,(180.f*theta/float32 Math.PI)-80.f,160.f)
            
 //end WaitControl   


type MainForm() as f =
    inherit Form()  
    
    let inputBox = new ListBox()
    let codeBox = new RichTextBox()
    let radioFix = new RadioButton()
    let radioTxt = new RadioButton()
    let radioCode = new RadioButton()
    let btnSave = new Button()
    let tooltip = new ToolTip()
    let btnCompile = new Button()
    let timer = new Timer(Interval=50)
    let mutable th:Thread = null
    let wc = new WaitControl(timer)

    let mutable degree, msg, dimen = 100.f, "", 2
  
    do
        f.Initialize()
        f.SetStyle(ControlStyles.OptimizedDoubleBuffer ||| ControlStyles.AllPaintingInWmPaint, true)
        timer.Tick.Add( 
            fun _ -> 
                degree<-(degree+5.f)%360.f
                dimen<-dimen-1
                if dimen<3 then 
                    dimen<-35+(int (degree/4.f)) //random
                    msg<-if Common.currentCell<>null then Common.currentCell else "PGS"
                
                if th<>null && not(th.IsAlive) then
                    f.Enabled<-true; wc.Visible<-false; inputBox.Visible<-true
                    timer.Stop(); 
                
                f.Invalidate()
        ) //endtimer
        
        inputBox.Visible<-false; f.Enabled<-false; f.Show()
        timer.Start()
        let ofd = new OpenFileDialog()
        ofd.Title <- "Select the spreadsheet file"
        ofd.Filter <- "Excel file|*.xls*|Formato ODS|*.ods"
        if ofd.ShowDialog() <> DialogResult.OK then
            Environment.Exit(-1)
        else
            th <- new Threading.Thread (Threading.ThreadStart
                      (fun _ -> 
                          try
                              Program.collector (ofd.FileName) 
                              for el in Program.maybeInputs do
                                  inputBox.Items.Add(el.Key)|>ignore
                          with |exc -> 
                              printfn "%s\n" exc.StackTrace
                              MessageBox.Show(exc.Message, "PGS", MessageBoxButtons.OK, MessageBoxIcon.Error) |>ignore
                      ) 
                  )
            th.Start()

        btnSave.Click.Add(
            fun _ -> if inputBox.SelectedIndex>=0 then
                        if radioFix.Checked then 
                            maybeInputs.[inputBox.SelectedItem.ToString()] <- {Tipo=Fixed; Source=null }
                        elif radioCode.Checked then 
                            maybeInputs.[inputBox.SelectedItem.ToString()] <- {Tipo=Custom; Source=codeBox.Text}
        )
        
        inputBox.SelectedIndexChanged.Add(
            fun _ ->
               
               tooltip.Active<-false

               try 
                   let elem = inputBox.SelectedItem.ToString() 
                   if elem.Contains(":") then
                       radioTxt.Enabled<-true
                   else radioTxt.Enabled<-false

                   let fonte = maybeInputs.[elem]
                   match fonte.Tipo with
                     | Fixed  -> radioFix.Select()
                     | TXT ->   codeBox.Text <- fonte.Source
                                radioTxt.Select()
                     | Custom -> radioCode.Select()
                                 codeBox.Enabled<-true
                                 codeBox.Text <- fonte.Source
                   inputBox.Focus() |>ignore
               with 
                 | _ -> radioFix.Select()
               tooltip.Active<-true
        )

        btnCompile.Click.Add( 
                fun _ -> 
                    try
                        let dlg = new FolderBrowserDialog()
                        dlg.Description <- "Select the ouput folder"
                        //timer.Start(); wc.Visible<-true; f.Enabled<-false;
                        if dlg.ShowDialog()=DialogResult.OK then
                            changeInputs()
                            Compile(dlg.SelectedPath)
                          //  wc.Visible<-false; f.Enabled<-true; timer.Stop()
                            MessageBox.Show("Compilation OK", "PGS") |>ignore
                            Application.Exit()
                    with
                        | exc ->
                            //timer.Stop(); f.Enabled<-true 
                            MessageBox.Show(exc.Message, "PGS", MessageBoxButtons.OK,MessageBoxIcon.Error) |>ignore
                            Application.Exit()
        )

    override f.OnPaint(e) =
        base.OnPaint(e)
        if timer.Enabled && inputBox.Visible=false then
            let g = e.Graphics
            g.TranslateTransform(140.f/2.f, 150.f/2.f)
            g.RotateTransform(degree)
            let font = new Font("Arial", float32 dimen, FontStyle.Bold)
            //let sz = g.MeasureString(msg, font)
            g.DrawString(msg, font, Brushes.Gray, -10.f,-3.f)//-(sz.Width/2.f), -(sz.Height/2.f))
            g.ResetTransform();
        //)
                    
    member private f.Initialize() =
        f.Text <- "Program Generator from Spreadsheet"
        f.ClientSize <- new System.Drawing.Size(550, 165)
        f.FormBorderStyle <- FormBorderStyle.FixedDialog
        f.MaximizeBox <- false

        wc.Location<-Point(210,100)
        
        inputBox.Location <- new System.Drawing.Point(15, 21)
        inputBox.Size <- new System.Drawing.Size(205, 95)
        
        radioFix.Text<-"Fixed"
        radioFix.Location <- new System.Drawing.Point(240, 21);
        radioFix.AutoSize <- true
        radioTxt.Text<-"TXT file"
        radioTxt.Location <- new System.Drawing.Point(290, 21);
        radioTxt.AutoSize <- true
        radioTxt.CheckedChanged.Add( 
            fun _ -> 
                if radioTxt.Checked then
                    if inputBox.SelectedItem=null then
                        radioFix.Select()
                    elif codeBox.Text.Length<3 then
                        let tdl = new OpenFileDialog()
                        tdl.Filter <- "TXT file|*.txt"
                        if tdl.ShowDialog() = DialogResult.OK then
                            codeBox.Text <- tdl.FileName
                            maybeInputs.[inputBox.SelectedItem.ToString()] <- {Tipo=TXT; Source=tdl.FileName}
                        else radioFix.Select()
                else codeBox.Text <- ""
        )
                                
        radioCode.Text<-"F# code"
        radioCode.Location <- new System.Drawing.Point(360, 21);
        radioCode.AutoSize <- true
        radioCode.CheckedChanged.Add( fun _ -> codeBox.Enabled<-radioCode.Checked )
        btnSave.Text <- "S a v e"
        btnSave.Size <- Size(75,18)
        btnSave.Location <- Point(435,18)

        codeBox.Location <- new System.Drawing.Point(235, 45);
        codeBox.Size <- new System.Drawing.Size(276, 72)
        codeBox.Enabled<-false
        
        tooltip.AutoPopDelay <- 20000
        tooltip.InitialDelay <- 250
        tooltip.ReshowDelay <- 100
        tooltip.OwnerDraw <- true
        tooltip.Draw.Add( fun e -> 
                e.DrawBackground() 
                if inputBox.SelectedItem=null then
                    let msg = if inputBox.Items.Count=0 then "   No inputs available" else "Select an option to see thumbnail"
                    e.Graphics.DrawString(msg, new Font("Times",10.f), Brushes.DarkBlue, 3.f,2.f)
                else
                    let img = Program.thumbs.[inputBox.SelectedItem.ToString()]
                    if img=null then
                        e.Graphics.DrawString("   No image available", new Font("Times",10.f), Brushes.DarkBlue, 3.f,2.f)
                    else
                        e.Graphics.DrawImage(img, new PointF(0.f,0.f))
        )
        tooltip.Popup.Add( fun e ->
                e.ToolTipSize <-
                   if (inputBox.SelectedItem=null) then
                       new Size(220, 22)
                   else
                       new Size(Native.THUMB_DIM, Native.THUMB_DIM)                  
        )
        tooltip.SetToolTip(inputBox, "Select an option to see a thumbnail")

        btnCompile.Text <- "C o m p i l e"
        btnCompile.Location <- new Point(f.ClientSize.Width/2-130, 130)
        btnCompile.Size <- Size(260, 20)

        f.Controls.Add(wc)
        f.Controls.Add(inputBox)
        f.Controls.Add(radioFix)
        f.Controls.Add(radioTxt)
        f.Controls.Add(radioCode)
        f.Controls.Add(codeBox)
        f.Controls.Add(btnSave)
        f.Controls.Add(btnCompile)
        f.Closed.Add( fun _ -> Program.app.Quit() )


[<STAThread>]
do
    Application.EnableVisualStyles();
    Application.Run(new MainForm())
